home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-11-08 | 70.6 KB | 2,104 lines |
- ;************************************************************************
- ;* *
- ;* PC Scheme/Geneva 4.00 Scheme code *
- ;* *
- ;* (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- ;* (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* A small adaptative text & scheme editor generator *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Created by: Marc Vuilleumier Date: Jan 1993 *
- ;* Revision history: *
- ;* - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- ;* *
- ;* ``In nomine omnipotentii dei'' *
- ;************************************************************************
- ; Note: this code contains too much lexical variables to be compiled
- ; with the debugging information. Use (SET! PCS-DEBUG-MODE #F)
-
- (begin
- (define make-editor)
- (define make-enhanced-editor)
- (define make-color-editor)
- (define make-scheme-editor)
- (define editor-handle-exit)
- )
-
- (let ; values shared by all editors
- ((fill ; tab expansion char
- (integer->char 255))
- (special-keys ; special escape keys
- '(0))
- (action-keys
- (list
- (cons (list* 072 000) '@up)
- (cons (list* 075 000) '@left)
- (cons (list* 077 000) '@right)
- (cons (list* 080 000) '@down)
- (cons (list* 073 000) '@page-up)
- (cons (list* 081 000) '@page-down)
- (cons (list* 071 000) '@home)
- (cons (list* 079 000) '@end)
- (cons (list* 132 000) '@top-of-buffer)
- (cons (list* 118 000) '@end-of-buffer)
- (cons (list* 034 000) '@goto-line) ; Alt-G
- (cons (list* 008) '@backspace)
- (cons (list* 083 000) '@del)
- (cons (list* 032 000) '@delete-line) ; Alt-D
- (cons (list* 037 000) '@delete-to-eol) ; Atl-K
- (cons (list* 023 000) '@insert) ; Alt-I
- (cons (list* 115 000) '@word-left)
- (cons (list* 116 000) '@word-right)
- (cons (list* 009) '@tab)
- (cons (list* 013) '@enter)
- (cons (list* 013 000) '@enter) ; Grey enter key
- (cons (list* 016 000) '@quote) ; Alt-Q
- (cons (list* 012) '@refresh) ; Ctrl-L: Refresh
- (cons (list* 017 000) '@write) ; Alt-W: Write file
- (cons (list* 018 000) '@load) ; Alt-E: Edit another file
- (cons (list* 019 000) '@read-into) ; Alt-R: Read into current
- (cons (list* 024 000) '@rename) ; Alt-O: New Output name
- (cons (list* 045 000) '@exit) ; Alt-X: Exit
- (cons (list* 065 000) '@record) ; F7
- (cons (list* 066 000) '@play) ; F8
- (cons (list* 068 000) '@execute) ; F10
- ))
- )
-
- (set! make-editor
- (lambda param
- (letrec
- ((input-port (if (port? (car param)) (car param) 'console))
- (win #F) ; Output port or #f for blind editor
- (nest 0) ; Nesting level
- (attr 7) ; Attribute for normal text
- (nlin 0) ; Number of lines/cols
- (ncol 0)
- (flin 1) ; First line/col displayed, last col
- (fcol 0)
- (lcol 0)
- (clin 1) ; Current line/col
- (ccol 0)
- (dim (cons nlin ncol)) ; Window size
- (todo #F) ; Top-level action to do when possible
- (buffer (list "" "")) ; The Buffer and its name
- (name (list "NONAME.S")) ; A pair: name and saved status-line
- (keys "")
- (modified #F) ; Modified? (need to save)
- (drty #F) ; Dirty? (need screen update)
- (mmov #F) ; Magic move? (redraw line)
- (recd #F) ; Recording ?
- (tab 8) ; Tab expansion length
- (tabulize-mode 'NORMAL) ; Tab compression mode
- (insert #T) ; Insert mode flag
- (bkp #T) ; Backup when saving flag
- (status-window pcs-status-window) ; Window for status line
- (separators ; Characters splitting two words
- (list->string (list #\space fill)))
-
- (magic (lambda (line)
- (when win
- (if (= line clin) (disppos))
- (when (eq? mmov 'hard)
- (window-set-attribute! win 'text-attributes attr)
- (window-scroll-up win (- line flin) (- line flin -1)))
- (if mmov (write-line win (list-ref buffer line) flin line fcol lcol)))))
-
- ; Key handling
-
- (@up (lambda ()
- (when (> clin 1)
- (when (and win (= flin clin))
- (set! flin (-1+ flin))
- (window-set-attribute! win 'text-attributes attr)
- (window-scroll-down win)
- (let ((str (list-ref buffer flin)))
- (write-line win str flin flin fcol lcol)))
- (set! clin (-1+ clin))
- (magic (1+ clin))
- (magic clin))
- ))
-
- (@left (lambda ()
- (when (> ccol 0)
- (set! ccol (-1+ ccol))
- (if (and win (> fcol 0) (< (- ccol fcol) 8))
- (begin (set! fcol (- fcol 10))
- (set! lcol (- lcol 10))
- (@refresh))
- (magic clin)))
- ))
-
- (@right (lambda ()
- (set! ccol (1+ ccol))
- (if (and win (= lcol ccol))
- (begin (set! fcol (+ fcol 10))
- (set! lcol (+ lcol 10))
- (@refresh))
- (magic clin))
- ))
-
- (@down (lambda ()
- (when (pair? (list-tail buffer (1+ clin)))
- (when (and win (= (1+ clin) (+ flin nlin)))
- (set! flin (1+ flin))
- (window-set-attribute! win 'text-attributes attr)
- (window-scroll-up win)
- (displl))
- (set! clin (1+ clin))
- (magic (-1+ clin))
- (magic clin))
- ))
-
- (@page-up (lambda ()
- (set! clin (max (1+ (- clin nlin)) 1))
- (set! flin (max (1+ (- flin nlin)) 1))
- (@refresh)))
-
- (@page-down (lambda ()
- (set! clin (-1+ (min (+ clin nlin) (length buffer))))
- (set! flin
- (min (-1+ (+ flin nlin)) (max 1 (- (length buffer) nlin))))
- (@refresh)))
-
- (@home (lambda ()
- (set! ccol 0)
- (if (> fcol 0)
- (begin (set! fcol 0)
- (set! lcol ncol)
- (@refresh))
- (magic clin))
- ))
-
- (@end (lambda ()
- (set! ccol (string-length (list-ref buffer clin)))
- (set! fcol (max 0 (1+ (- ccol ncol))))
- (if (not (= lcol (+ fcol ncol)))
- (begin (set! lcol (+ fcol ncol))
- (@refresh))
- (magic clin))
- ))
-
- (@top-of-buffer (lambda ()
- (set! clin 1)
- (set! flin 1)
- (@refresh)))
-
- (@end-of-buffer (lambda ()
- (set! clin (-1+ (length buffer)))
- (checkp)))
-
- (@goto-line (lambda ()
- (let* ((line clin)
- (str (with-status
- (lambda (mes)
- (displayp "Go to line: " mes)
- (read-linep mes)))))
- (when (not (eqv? str ""))
- (set! clin (string->number str))
- (if (< clin 1) (set! clin 1))
- (if (null? (list-tail buffer clin))
- (set! clin (-1+ (length buffer))))
- (checkp)))))
-
- (@backspace (lambda ()
- (when (> ccol 0)
- (let* ((curr (list-tail buffer clin))
- (len (string-length (car curr))))
- (set! modified #T)
- (set-car! curr
- (string-append
- (substring (car curr) 0 (min (-1+ ccol) len))
- (substring (car curr) (min ccol len) len)))
- (@left)
- (write-line win (string-append (car curr) " ") flin clin fcol lcol)))
- ))
-
- (@del (lambda ()
- (let* ((curr (list-tail buffer clin))
- (len (string-length (car curr)))
- (rest (substring (car curr) (min ccol len) len)))
- (set! modified #T)
- (if (and (eqv? rest (make-string (string-length rest) #\space))
- (cdr curr))
- (begin
- (set-car! curr
- (string-append
- (substring (car curr) 0 (min ccol len))
- (make-string (max 0 (- ccol len)) fill)
- (cadr curr)))
- (set-cdr! curr (cddr curr))
- (when win
- (window-set-attribute! win 'text-attributes attr)
- (window-scroll-up win (- clin flin -1))
- (displl)))
- (set-car! curr
- (string-append
- (substring (car curr) 0 (min ccol len))
- (substring (car curr) (min (1+ ccol) len) len))))
- (write-line win (string-append (car curr) " ") flin clin fcol lcol))
- ))
-
- (@delete-to-eol (lambda ()
- (let ((curr (list-tail buffer clin)))
- (set-car! curr (substring (car curr) 0
- (min ccol (string-length (car curr))))))
- (refresh-line)))
-
- (@delete-line (lambda ()
- (let ((curr (list-tail buffer (-1+ clin))))
- (set! modified #T)
- (set-cdr! curr (or (cddr curr) (if (= clin 1) (list ""))))
- (when win
- (window-set-attribute! win 'text-attributes attr)
- (window-scroll-up win (- clin flin)))
- (if (null? (cdr curr))
- (begin (set! clin (-1+ clin))
- (checkp))
- (displl))
- (magic clin))
- ))
-
- (@insert (lambda ()
- (set! insert (not insert))
- ))
-
- (@word-left (lambda ()
- (let ((str (list-ref buffer clin)))
- (do ((new ccol (substring-find-previous-char-in-set str 0 (min ccol (string-length str)) separators)))
- ((or (null? new) (< new (-1+ ccol))) (set! ccol (if (null? new) 0 (1+ new))))
- (set! ccol new)))
- (if (and (> fcol 0) (< (- ccol fcol) 8))
- (begin (set! fcol (* 10 (min 0 (quotient (- ccol 8) 10))))
- (set! lcol (+ fcol ncol))
- (@refresh))
- (magic clin))
- ))
-
- (@word-right (lambda ()
- (let* ((str (list-ref buffer clin))
- (len (string-length str)))
- (set! ccol (substring-find-next-char-in-set str (min ccol len) len separators))
- (if (null? ccol)
- (set! ccol len)
- (do ((new ccol (substring-find-next-char-in-set str (min ccol len) len separators)))
- ((or (null? new) (> new ccol)) '())
- (set! ccol (1+ new)))))
- (if (>= ccol lcol)
- (begin (set! fcol (* 10 (1+ (quotient (- ccol ncol) 10))))
- (set! lcol (+ fcol ncol))
- (@refresh))
- (magic clin))
- ))
-
- (@tab (lambda ()
- (let ((ins insert))
- (set! insert #t)
- (insert-string (make-string (- tab (remainder ccol tab)) fill))
- (set! insert ins))))
-
- (@enter (lambda ()
- (when insert
- (let* ((curr (list-tail buffer clin))
- (str (car curr))
- (len (string-length str))
- (cut (min len ccol))
- (line (- clin flin)))
- (set! modified #T)
- (set-car! curr (substring str 0 cut))
- (set-cdr! curr (cons (substring str cut len) (cdr curr)))
- (when win
- (window-set-attribute! win 'text-attributes attr)
- (window-scroll-down win (1+ line))
- (when (< cut len)
- (window-set-attribute! win 'text-attributes attr)
- (window-scroll-down win line (1+ line))
- (write-line win (car curr) flin clin fcol lcol))
- (when (< (1+ line) nlin)
- (write-line win (cadr curr) flin (1+ clin) fcol lcol)))))
- (@down)
- (@home)))
-
- (@quote (lambda ()
- (let ((prev-actions actions)
- (prev-specials specials))
- (set! actions action-keys)
- (set! specials special-keys)
- (notify "Press a Basic-editor key...")
- (set! actions prev-actions)
- (set! specials prev-specials)
- )))
-
- (@refresh (lambda ()
- (if (char-ready? input-port)
- (set! drty #t)
- (when win
- (set! drty #f)
- (refresh-lines flin (+ flin nlin))))))
-
- (@write (lambda ()
- (save (namep))
- (notify "File " (namep) " written.")
- ))
-
- (@load (lambda ()
- (let* ((name (with-status
- (lambda (mes)
- (displayp "Edit another file: " mes)
- (read-linep mes)))))
- (when (not (eqv? name ""))
- (safe)
- (clear name)
- (if (file-exists? name)
- (loadp name))))
- (@refresh)))
-
- (@read-into (lambda ()
- (set! modified #T)
- (let ((name (with-status
- (lambda (mes)
- (displayp "Read and insert file: " mes)
- (read-linep mes)))))
- (when (not (eqv? name ""))
- (if (file-exists? name)
- (loadp name))))
- (@refresh)))
-
- (@rename (lambda ()
- (let ((name (with-status
- (lambda (mes)
- (displayp "Give another name to buffer: " mes)
- (read-linep mes)))))
- (when (not (eqv? name ""))
- (namep name)
- (set! modified #T)))
- ))
-
- (@exit (lambda ()
- (set! todo 'exit)
- ))
-
- (@record (lambda ()
- (set! recd (not recd))
- (if recd
- (set! keys "")
- (let* ((rev (lambda (p) (cons (cdr p) (car p))))
- (seq (cdr (assq '@record (map rev actions))))
- (len (apply (lambda l (length l)) seq)))
- (set! keys (substring keys 0 (- (string-length keys) len)))))
- (notify (if recd
- "Recording keystroke macro"
- "Keystroke macro defined"))
- ))
-
- (@play (lambda ()
- (if recd
- (let* ((rev (lambda (p) (cons (cdr p) (car p))))
- (seq (cdr (assq '@play (map rev actions))))
- (len (apply (lambda l (length l)) seq)))
- (set! keys (substring keys 0 (- (string-length keys) len))))
- (do-string keys))
- ))
-
- (@execute (lambda ()
- (let* ((f (open-input-string
- (string-append
- "("
- (with-status
- (lambda (mes)
- (displayp "Message: " mes)
- (read-linep mes)))
- ")")))
- (args (read f))
- (result (if (assq (car args) jobs)
- (apply me args)
- #!unassigned)))
- (handle-action
- (with-status
- (lambda (mes)
- (when mes
- (display "Result: " mes)
- (write result mes)
- (read-action))))))))
-
- ; main subfonctions
-
- (checkp (lambda () ; valid cursor/screen position
- (let ((oldc fcol) (oldl flin))
- (if (>= (- ccol fcol -2) ncol) (set! fcol (- ccol ncol -3)))
- (if (>= (- clin flin -2) nlin) (set! flin (- clin nlin -3)))
- (if (<= (- ccol fcol) 2) (set! fcol (max 0 (- ccol 2))))
- (if (<= (- clin flin) 2) (set! flin (max 1 (- clin 2))))
- (set! lcol (+ fcol ncol))
- (if (not (and (= oldc fcol) (= oldl flin)))
- (if (and win (= oldc fcol) (< (abs (- oldl flin)) 10))
- (if (< oldl flin)
- (do ((line oldl (1+ line)))
- ((= line flin) (refresh-lines (+ oldl nlin)
- (+ flin nlin)))
- (window-scroll-up win 0 nlin))
- (do ((line oldl (-1+ line)))
- ((= line flin) (refresh-lines flin
- (+ flin (- oldl flin))))
- (window-scroll-down win 0 nlin)))
- (@refresh))
- (disppos))
- (if win (window-set-cursor! win (- clin flin) (- ccol fcol)))
- )))
-
- (with-status (lambda (proc) ; call proc with popup status window
- (if win
- (begin
- (window-popup status-window)
- (begin0
- (proc status-window)
- (window-popup-delete status-window)))
- (proc #F))))
-
- (displayp (lambda l ; display items (on status)
- (when (and (pair? l) (pair? (cdr l)) (car (last-pair l)))
- (display (car l) (car (last-pair l)))
- (apply displayp (cdr l)))))
-
- (read-linep (lambda (port) ; read a line and record entry
- (let ((str (read-line
- (if (and port
- (window? input-port)
- (not (input-string? input-port)))
- port
- input-port))))
- (if recd
- (set! keys (string-append keys str (string #\RETURN))))
- str)))
-
- (notify (lambda l ; write string[s] on status and proceed
- (handle-action
- (with-status
- (lambda (mes)
- (set-cdr! (last-pair l) mes)
- (apply displayp l)
- (read-action))))))
-
- (clear (lambda (name) ; clear buffer
- (set! buffer (list "" ""))
- (namep name)
- (set! modified #F)
- (set! clin 1)
- (set! flin 1)
- (gc #T)))
-
- (make-blank (lambda (len)
- (make-string len (if (eq? tabulize-mode 'expand)
- #\space
- fill))))
-
- (substring-skip (lambda (str pos end)
- (cond ((>= pos end) end)
- ((or (eqv? (string-ref str pos) #\space)
- (eqv? (string-ref str pos) fill))
- (substring-skip str (1+ pos) end))
- (else pos))))
-
- (untabulize (lambda (str) ; de-tabulize a line when loading
- (let* ((len (string-length str))
- (pos (substring-find-next-char-in-set str 0 len #\tab)))
- (if (or (null? pos) (= tab 0))
- str
- (string-append
- (substring str 0 pos)
- (make-blank (- tab (remainder pos tab)))
- (untabulize (substring str (1+ pos) len)))))))
-
- (loadp (lambda (name) ; load a file into editor
- (with-status
- (lambda (mes)
- (displayp "Loading " name mes)
- (let ((fil (open-input-file name)))
- (do ((cur (list-tail buffer (-1+ clin)) (cdr cur)))
- ((eof-object? (peek-char fil)) *the-non-printing-object*)
- (set-cdr! cur (cons (untabulize (read-line fil)) (cdr cur)))
- (read-char fil)) ; skip LF
- (close-input-port fil))
- (gc #T)))))
-
- (tabulize (lambda (str) ; re-tabulize a line for saving
- (let ((len (string-length str)))
- (if (not (eq? tabulize-mode 'normal))
- (do ((idx (-1+ (string-length str)) (-1+ idx))
- (fnd (if (eq? tabulize-mode 'compress) #\space fill))
- (rep (if (eq? tabulize-mode 'expand) #\space fill)))
- ((< idx 0))
- (if (char=? (string-ref str idx) fnd)
- (string-set! str idx rep))))
- ((named-lambda (loop start parts)
- (let* ((pos (substring-find-next-char-in-set str start len fill)))
- (if (not pos)
- (if (null? parts)
- str
- (apply string-append
- (reverse
- (if (= start len)
- (cddr parts)
- (cons (substring str start len) parts)))))
- (let*
- ((num ((named-lambda (count pos num)
- (if (and (< pos len)
- (char=? (string-ref str pos) fill))
- (count (1+ pos) (1+ num))
- num))
- (1+ pos) 1))
- (rul (+ num (remainder pos tab)))
- (adj (if (< rul 8) num rul)))
- (loop
- (+ pos num)
- (list*
- (make-string (remainder adj tab) #\space)
- (make-string (quotient adj tab) #\tab)
- (substring str start pos)
- parts))))))
- 0 '()))))
-
- (save (lambda (name) ; save current file
- (with-status
- (lambda (mes)
- (displayp "Writing " name mes)
- (set! modified #F)
- (if (and bkp (file-exists? name))
- (let* ((l (reverse (filename-split name)))
- (ext (if (string-ci=? (car l) ".bak") ".$$$" ".bak"))
- (new (filename-merge (reverse (cons ext (cdr l))))))
- (if (file-exists? new) (delete-file new))
- (dos-rename name new)))
- (let ((fil (open-output-file name)))
- (do ((curr (cdr buffer) (cdr curr)))
- ((or (null? curr)
- (and (null? (cdr curr))
- (eqv? (car curr) "")))
- *the-non-printing-object*)
- (display (tabulize (car curr)) fil)
- (newline fil))
- (close-output-port fil))
- (gc #T)))))
-
- (displl (lambda () ; display last line
- (let* ((clin (+ flin nlin -1))
- (str (list-ref buffer clin)))
- (if (not (null? str)) (write-line win str flin clin fcol lcol)))))
-
- (write-line (lambda (win str flin clin fcol lcol); fit-in and display line
- (when (and win (> (string-length str) fcol))
- (window-set-cursor! win (- clin flin) 0)
- (display
- (substring str fcol (min (string-length str) lcol))
- win))))
-
- (refresh-lines (lambda (start end)
- (let ((start (max start flin))
- (end (max 0 (min nlin (- end flin)))))
- (do ((cur (list-tail buffer start) (cdr cur))
- (n (- start flin) (1+ n)))
- ((>= n end))
- (window-set-attribute! win 'text-attributes attr)
- (window-scroll-up win n (1+ n))
- (if cur (write-line win (car cur) flin (+ flin n) fcol lcol))))
- (disppos)))
-
- (refresh-line (lambda () ; refresh current line
- (when win
- (window-set-attribute! win 'text-attributes attr)
- (window-scroll-up win (- clin flin) (- clin flin -1))
- (write-line win (list-ref buffer clin) flin clin fcol lcol)
- (disppos))))
-
- ; Key processing
-
- (actions action-keys)
- (specials special-keys)
-
- (inkey (lambda (char)
- (when recd
- (if win (display (integer->char 7)))
- (set! keys (string-append keys (string char))))
- (char->integer char)))
-
- (read-action (lambda () ; read and handle a key
- (when win
- (if (and drty (not (char-ready? input-port)))
- (@refresh)
- (window-set-cursor! win (- clin flin) (- ccol fcol))))
- ((named-lambda (decode char)
- (or (cdr (assoc char actions))
- (if (member char specials)
- (if (char-ready? input-port)
- (decode (cons (inkey (read-char input-port)) char))
- (with-status
- (lambda (mes)
- (write char mes)
- (decode (cons (inkey (read-char input-port)) char))))))
- (if (and (integer? char)
- (>= char 32)
- (<= char 255))
- (integer->char char))
- char
- ))
- (inkey (read-char input-port)))))
-
- (handle-action (lambda (action) ; handle a key-combination
- (cond
- ((char? action)
- (insert-string (string action)))
- ((symbol? action)
- ((dispatch action)))
- ((string? action)
- (do-string action))
- ((proc? action)
- (action me))
- ((and (pair? action)
- (pair? (car action)))
- (if ((caar action) me)
- (handle-action (cdar action))
- (handle-action (cdr action))))
- (else
- (if win (display (integer->char 7)))))))
-
- (insert-string (lambda (instr)
- (let* ((curr (list-tail buffer clin))
- (len (string-length instr))
- (diff (- (string-length (car curr)) ccol))
- (str (if (>= diff 0)
- (car curr)
- (string-append
- (car curr)
- (make-blank (- diff)))))
- )
- (set! modified #T)
- (set-car! curr
- (string-append
- (substring str 0 ccol)
- instr
- (substring str
- (if insert
- ccol
- (+ ccol (min len (max diff 0))))
- (+ ccol (max diff 0)))))
- (write-line win (car curr) flin clin fcol lcol)
- (set! ccol (+ ccol len -1))
- (@right))))
-
- ; Interface support
-
- (do-string (lambda (str) ; feed input port with keys
- (let ((old input-port)
- (asc "")
- (magic-move mmov))
- (set! mmov #f)
- (set! input-port (open-input-string str))
- (do ((doasc (lambda () (when (not (eqv? asc ""))
- (insert-string asc)
- (set! asc "")))))
- ((eof-object? (peek-char input-port)) (doasc))
- (let ((action (read-action)))
- (if (char? action)
- (set! asc (string-append asc (string action)))
- (begin (doasc) (handle-action action)))))
- (set! input-port old)
- (set! mmov magic-move)
- (refresh-line)
- )))
-
- (remap-key (lambda (key func) ; map a function to a key
- (let ((found (assoc key actions)))
- (if found
- (set-cdr! found func)
- (begin
- (set-cdr! actions (cons (cons key func) (cdr actions)))
- (if (pair? key)
- ((named-lambda (scan prefix)
- (when (not (member prefix specials))
- (set-cdr! prefix (cons prefix (cdr prefix)))
- (if (pair? prefix) (scan (cdr prefix)))))
- (cdr key))))))))
-
- (position (lambda l ; set/get cursor/screen position
- (begin0
- (list clin ccol flin fcol)
- (when l
- (set! clin (caar l))
- (set! ccol (cadar l))
- (when (cddar l)
- (set! flin (car (cddar l)))
- (set! fcol (cadr (cddar l))))
- (checkp)))))
-
- (safe (lambda () ; ensure modified buffer is saved
- (if modified
- (begin
- (when win (window-popup win) (@refresh))
- (begin0
- (with-status
- (lambda (mes)
- (displayp "File " (namep) " modified. Save (Y/N/Esc) ?" mes)
- ((named-lambda (loop)
- (case (read-char (or mes input-port))
- ((#\y #\Y) (@write) #T)
- ((#\n #\N) #T)
- (#\escape #F)
- (else (loop)))))))
- (if win (window-popup-delete win))))
- #T)))
-
- (window (lambda w ; set up the output port
- (begin0
- (cons win (cons nlin ncol))
- (when w
- (set! win (if (window? (car w)) (car w) #F))
- (set! dim (if win (window-get-size win) '(32000 . 32000)))
- (set! nlin (car dim))
- (set! ncol (cdr dim))
- (if (>= (- ccol fcol) ncol) (set! fcol (- ccol ncol -1)))
- (if (>= (- clin flin) nlin) (set! flin (- clin nlin -1)))
- (set! lcol (+ fcol ncol))))))
-
- (status-bg (lambda (status-window name)
- (window-clear status-window)
- (display name status-window)
- (window-set-cursor! status-window 0 50)
- (display "Line: " status-window)
- (window-set-cursor! status-window 0 65)
- (display "Col: " status-window)))
-
- (status-fg (lambda (status-window clin ccol)
- (window-set-cursor! status-window 0 56)
- (display clin status-window)
- (window-set-cursor! status-window 0 70)
- (display (1+ ccol) status-window)))
-
- (namep (lambda l
- (let ((old (car name)))
- (when l
- (if (and win status-window)
- (begin
- (status-bg status-window (car l))
- (set! name (cons (car l) (window-save-contents status-window)))
- (status-fg status-window clin ccol)
- )
- (set! name (list (car l)))))
- old)))
-
- (disppos (lambda ()
- (when (and win status-window)
- (if (cdr name)
- (window-restore-contents status-window (cdr name))
- (namep (namep)))
- (status-fg status-window clin ccol))))
-
- ; Open an editor, proceed it and hide it
-
- (open (lambda arg
- (if win (window-popup win))
- (when (and (string? (car arg)) (safe))
- (clear (car arg))
- (loadp (car arg)))
- (@refresh)
- (set! todo #F)
- (do () (todo #F) (handle-action (read-action)))
- (if win (window-popup-delete win))
- (case todo
- ('exit *the-non-printing-object*)
- (else todo))))
-
- ; Message handling
-
- (jobs (append
- (list
- (cons '@up @up)
- (cons '@left @left)
- (cons '@right @right)
- (cons '@down @down)
- (cons '@page-up @page-up)
- (cons '@page-down @page-down)
- (cons '@home @home)
- (cons '@end @end)
- (cons '@top-of-buffer @top-of-buffer)
- (cons '@end-of-buffer @end-of-buffer)
- (cons '@goto-line @goto-line)
- (cons '@backspace @backspace)
- (cons '@del @del)
- (cons '@delete-line @delete-line)
- (cons '@delete-to-eol @delete-to-eol)
- (cons '@insert @insert)
- (cons '@word-left @word-left)
- (cons '@word-right @word-right)
- (cons '@enter @enter)
- (cons '@tab @tab)
- (cons '@quote @quote)
- (cons '@refresh @refresh)
- (cons '@write @write)
- (cons '@load @load)
- (cons '@read-into @read-into)
- (cons '@rename @rename)
- (cons '@exit @exit)
- (cons '@record @record)
- (cons '@play @play)
- (cons '@execute @execute))
- (list
- (cons 'open open) ; generic call (automatic)
- (cons 'read-action read-action) ; read and decode one action
- (cons 'handle-action handle-action); handle one action
- (cons 'do-string do-string) ; send string to char handler
- (cons 'remap-key remap-key) ; assign a function to a key
- (cons 'clear clear) ; clear buffer
- (cons 'refresh-lines refresh-lines); refresh part of screen
- (cons 'refresh-line refresh-line) ; refresh current line
- (cons 'with-status with-status) ; handle display in status line
- (cons 'display displayp) ; display, canceled if editor is off-screen
- (cons 'read-line read-linep) ; read, from input-port if editor off-screen
- (cons 'notify notify) ; signal something on status line
- (cons 'load loadp) ; load file at current line into buffer
- (cons 'save save) ; write file with buffer
- (cons 'make-blank make-blank) ; make a "blank" string of given length
- (cons 'substring-skip substring-skip); return pos of the next non-blank char
- (cons 'untabulize untabulize) ; expand tabs to #\255
- (cons 'tabulize tabulize) ; squish #\255 to tabs
- (cons 'safe safe) ; ensure buffer saved if necessary
- (cons 'position position) ; set/get all position pointers
- (cons 'window window) ; use a new/get port for I/O
- (cons 'name namep)) ; get/set the buffer's name
- (list
- (cons 'insert (lambda l (begin0 insert (if l (set! insert (car l))))))
- (cons 'magic-move (lambda l (begin0 mmov (if l (set! mmov (car l))))))
- (cons 'tab (lambda l (begin0 tab (if l (set! tab (car l))))))
- (cons 'tabulize-mode (lambda l (begin0 tabulize-mode (if l (set! tabulize-mode (car l))))))
- (cons 'buffer (lambda l (begin0 buffer (if l (set! buffer (car l))))))
- (cons 'modified (lambda l (begin0 modified (if l (set! modified (car l))))))
- (cons 'todo (lambda l (begin0 todo (if l (set! todo (car l))))))
- (cons 'actions (lambda l (begin0 actions (if l (set! actions (car l))))))
- (cons 'specials (lambda l (begin0 specials (if l (set! specials (car l))))))
- (cons 'separators (lambda l (begin0 separators (if l (set! separators (car l))))))
- (cons 'input-port (lambda l (begin0 input-port (if l (set! input-port (car l))))))
- (cons 'status-window (lambda l (begin0 status-window (if l (set! status-window (car l))))))
- (cons 'status-fg (lambda l (begin0 status-fg (if l (set! status-fg (car l))))))
- (cons 'status-bg (lambda l (begin0 status-bg (if l (set! status-bg (car l))))))
- (cons 'write-line (lambda l (begin0 write-line (if l (set! write-line (car l))))))
- (cons 'jobs (lambda l (begin0 jobs (if l (set! jobs (car l))))))
- (cons 'who (lambda l (begin0 me (if l (set! me (car l)))))))
- ))
-
- (dispatch (lambda (it)
- (let ((task (assq it jobs)))
- (if task
- (cdr task)
- (lambda args (%error-invalid-operand 'editor it))))))
-
- (me (lambda args
- (let* ((sta (when (= nest 0)
- (window input-port)
- (window-save-contents status-window))))
- (set! nest (1+ nest))
- (if (or (null? args) (string? (car args))) ; implicit selector
- (set! args (cons 'open args)))
- (begin0 (apply (dispatch (car args)) (cdr args))
- (set! nest (-1+ nest))
- (if (= nest 0)
- (window-restore-contents status-window sta))))
- ))
-
- ) ; LETREC bindings
-
- (if (not (memq 'EXIT-FREELY param))
- (editor-handle-exit 'remember me))
- (if (window? input-port)
- (set! attr (window-get-attribute input-port 'text-attributes)))
- me
-
- ) ; LETREC
- ) ; LAMBDA param
- ) ; SET! make-editor
- ) ; LET
-
-
- ;**************************************************************************
- ; This is how to derive an enhanced editor from the previous one...
-
-
- (let* ; values shared by all editors
- ((scrap '(line)) ; scrapboard (block-type . (text))
-
- (block? (lambda (ed) ; context discriminator
- (car (ed 'select))))
-
- (special-keys
- (cons '(36 . 0) ((make-editor 'EXIT-FREELY) 'specials)))
-
- (action-keys
- (append
- (list
- (cons (list* 050 000) '@mark-block) ; Alt-M: Mark region
- (cons (list* 038 000) '@line-block) ; Alt-L: Line region
- (cons (list* 046 000) '@column-block) ; Alt-C: Column region
- (cons (list* 082 000) '@insert-block) ; Ins: Paste block
- (cons (list* 083 000) (list* (cons block? '@delete-block)
- '@del)) ; Del: Delete char or block
- (cons (list* 043) (list* (cons block? '@copy-block)
- #\+)) ; '+': Copy blcok
- (cons (list* 045) (list* (cons block? '@cut-block)
- #\-)) ; '-': Cut blcok
- (cons (list* 047) (list* (cons block? '@swap-anchor)
- #\/)) ; '/': Swap mark & cursor
- (cons (list* 017 000) (list* (cons block? '@write-block)
- '@write)) ; Alt-W: Write file or block
- (cons (list* 018) '@replicate) ; Ctrl-R
- (cons (list* 031 000) '@search) ; Alt-S
- (cons (list* 020 000) '@translate) ; Alt-T
- (cons (list* 063 000) '@search) ; F5
- (cons (list* 088 000) '@repeat-search) ; Shift-F5
- (cons (list* 064 000) '@translate) ; F6
- (cons (list* 089 000) '@repeat-translate); Shift-F6
- (cons (list* 098 000) '@case-sensitivity); Ctrl-F5
- (cons (list* 120 000) '@bookmark-1) ; Alt-[1-3]
- (cons (list* 121 000) '@bookmark-2)
- (cons (list* 122 000) '@bookmark-3)
- (cons (list* 49 36 0) '@jump-to-1) ; Alt-J [1-3]
- (cons (list* 50 36 0) '@jump-to-2)
- (cons (list* 51 36 0) '@jump-to-3)
- )
- ((make-editor 'EXIT-FREELY) 'actions)))
- )
-
- (set! make-enhanced-editor
- (lambda param
- (letrec
- (
- (ed (apply make-editor param))
-
- (btyp #f) ; block type: {#f 'line 'char 'col}
- (blin 1) ; start of block
- (bcol 0)
- (mtyp #f) ; magic-move-mode to restore
- (epos '())
- (win #F)
- (clin 1)
- (ccol 0)
- (flin 1)
- (fcol 0)
- (mmov #f)
- (top 1)
- (bot 1)
- (bookmarks (make-vector 10 '(1 0 1 0)))
- (case-sensitivity #t) ; default to case-sensitive
- (search-objects (list "" "" ""))
-
- ; Key handling support
-
- (get-values (lambda ()
- (set! mmov (ed 'magic-move))
- (set! epos (ed 'position))
- (set! clin (car epos))
- (set! ccol (cadr epos))
- (set! flin (caddr epos))
- (set! fcol (cadddr epos))
- (set! top (min blin clin))
- (set! bot (max blin clin))
- ))
-
- (refresh (lambda (newlin)
- (if (= flin (caddr (ed 'position (list newlin ccol))))
- (ed 'refresh-lines (min clin newlin)
- (if (eq? (car scrap) 'col)
- (1+ (max clin newlin))
- (length (ed 'buffer)))))))
-
- ; Key handling
-
- (@mark (lambda (type)
- (lambda ()
- (if (eq? btyp type)
- (@cancel-block)
- (begin
- (get-values)
- (when (not btyp)
- (if mmov (ed 'magic-move 'hard))
- (set! mtyp mmov)
- (set! bcol ccol)
- (set! blin clin))
- (set! btyp type)
- (get-values)
- (if mmov (ed 'refresh-lines top (1+ bot))))))))
-
- (@cancel-block (lambda ()
- (when btyp
- (get-values)
- (if mtyp (ed 'magic-move mtyp))
- (set! btyp #f)
- (if mmov (ed 'refresh-lines top (1+ bot))))))
-
- (@insert-block (lambda ()
- (get-values)
- (let* ((ante (list-tail (ed 'buffer) (-1+ clin)))
- (str (cadr ante))
- (len (string-length str))
- (putline (named-lambda (putline scrap)
- (when scrap
- (set-cdr! ante (cons (car scrap) (cdr ante)))
- (putline (cdr scrap)))))
- )
- (case (car scrap)
- ('line (putline (cdr scrap)))
- ('char (let ((fstr (substring str 0 ccol)))
- (set-car! (cdr ante) (string-append
- (cadr scrap)
- (substring str ccol len)))
- (putline (cddr scrap))
- (set-car! (cdr ante) (string-append fstr (cadr ante)))
- (set! ccol (+ (string-length (cadr scrap))
- (if (null? (cddr scrap)) ccol 0)))
- ))
- ('col ((named-lambda (putline scrap ante)
- (when scrap
- (cond
- ((null? (cdr ante))
- (set-cdr! ante
- (list (string-append
- (ed 'make-blank ccol)
- (car scrap)))))
- ((<= (string-length (cadr ante)) ccol)
- (set-car! (cdr ante)
- (string-append
- (cadr ante)
- (ed 'make-blank (- ccol (string-length (cadr ante))))
- (car scrap))))
- (else
- (set-car! (cdr ante)
- (string-append
- (substring (cadr ante) 0 ccol)
- (car scrap)
- (substring (cadr ante) ccol
- (string-length (cadr ante)))))))
- (putline (cdr scrap) (cdr ante))
- ))
- (reverse (cdr scrap)) ante)
- (set! ccol (+ ccol (string-length (cadr scrap)))))
- ))
- (refresh (+ clin (length scrap)
- (if (eq? (car scrap) 'col) -1 -2)))
- ))
-
- (@delete-block (lambda ()
- (let ((old scrap))
- (@cut-block)
- (set! scrap old))
- (ed 'notify "Block deleted")
- ))
-
- (@copy-block (lambda ()
- (get-values)
- (when (not btyp)
- (set! btyp 'line)
- (set! blin clin))
- (set! scrap '())
- (do ((curr (list-tail (ed 'buffer) top) (cdr curr))
- (n top (1+ n))
- (width (1+ (abs (- bcol ccol)))))
- ((> n bot))
- (let* ((str (car curr))
- (len (string-length str))
- (sran (srange n 0 len))
- (spac (- width (- (cdr sran) (car sran)))))
- (set! scrap
- (cons (if (eq? btyp 'col)
- (string-append
- (substring str (car sran) (cdr sran))
- (ed 'make-blank spac))
- (substring str (car sran) (cdr sran)))
- scrap))))
- (set! scrap (cons btyp scrap))
- (@cancel-block)
- (ed 'notify "Block copied to scrap")
- ))
-
- (@cut-block (lambda ()
- (get-values)
- (when (not btyp)
- (set! btyp 'line)
- (set! blin clin))
- (set! scrap '())
- (let* ((ante (list-tail (ed 'buffer) (-1+ top)))
- (last (list-tail ante (1+ (- bot top)))))
- (case btyp
- ('line (set! scrap (cdr ante))
- (set-cdr! ante (cdr last))
- (set-cdr! last '())
- (set! scrap (reverse! scrap)))
- ('char (let* ((flen (string-length (cadr ante)))
- (fran (srange top 0 flen))
- (fstr (substring (cadr ante) (car fran) (cdr fran)))
- (llen (string-length (car last)))
- (lran (srange bot 0 llen))
- )
- (set-car! (cdr ante)
- (string-append
- (substring (cadr ante) 0 (car fran))
- (substring (car last) (cdr lran) llen)))
- (when (<> top bot)
- (set! scrap (cddr ante))
- (set-cdr! (cdr ante) (cdr last))
- (set-car! last (substring (car last) 0 (cdr lran)))
- (set-cdr! last '()))
- (set! scrap (reverse! (cons fstr scrap)))))
- ('col (do ((curr (cdr ante) (cdr curr))
- (line top (1+ line))
- (width (1+ (abs (- bcol ccol)))))
- ((> line bot))
- (let* ((len (string-length (car curr)))
- (sran (srange line 0 len))
- (spac (- width (- (cdr sran) (car sran)))))
- (set! scrap
- (cons (string-append
- (substring (car curr) (car sran) (cdr sran))
- (ed 'make-blank spac))
- scrap))
- (set-car! curr
- (string-append
- (substring (car curr) 0 (car sran))
- (substring (car curr) (cdr sran) len))))))
- ))
- (if mtyp (ed 'magic-move mtyp))
- (set! scrap (cons btyp scrap))
- (set! btyp #f)
- (set! ccol (if (= clin top) (min ccol bcol) bcol))
- (set! clin bot)
- (refresh top)
- (ed 'notify "Block deleted to scrap")
- ))
-
- (@write-block (lambda ()
- (when btyp
- (ed 'with-status
- (lambda (mes)
- (ed 'display "Write block as: " mes)
- (let ((name (ed 'read-line mes)))
- (when
- (or (not mes)
- (not (file-exists? name))
- (begin
- (window-clear mes)
- (display "Overwrite existing file (Y/N) ? " mes)
- ((named-lambda (loop)
- (case (read-char mes)
- ((#\y #\Y) #T)
- ((#\n #\N) #F)
- (else (loop)))))))
- (write-block name))))))))
-
- (@swap-anchor (lambda ()
- (when btyp
- (get-values)
- (set! epos (list blin bcol))
- (set! blin clin)
- (set! bcol ccol)
- (ed 'position epos)
- )))
-
- (@replicate (lambda ()
- (let* ((input-port (ed 'input-port))
- (action '())
- (count
- (string->number
- (ed 'with-status (lambda (mes)
- (ed 'display "Enter count, then press the key to replicate: " mes)
- ((named-lambda (loop)
- (let ((key (ed 'read-action)))
- (if (and (char? key)
- (char>=? key #\0)
- (char<=? key #\9))
- (begin
- (ed 'display key mes)
- (string-append (string key) (loop)))
- (begin
- (set! action key)
- "")))))
- ))))
- )
- (if (char? action)
- (ed 'do-string (make-string count action))
- (do ((magic-move (ed 'magic-move #f))
- (idx count (-1+ idx)))
- ((<= idx 0)(ed 'magic-move magic-move))
- (ed 'handle-action action)))
- (ed 'refresh-line)
- )))
-
- (@bookmark (lambda (n)
- (lambda ()
- (let ((pos (ed 'position)))
- (set-cdr! (cdr pos) '())
- (vector-set! bookmarks n pos))
- (ed 'notify "Bookmark " n " dropped")
- )))
-
- (@jump-to (lambda (n)
- (lambda ()
- (ed 'position (vector-ref bookmarks n)))))
-
- (@case-sensitivity (lambda ()
- (set! case-sensitivity (not case-sensitivity))
- (ed 'notify "Case sensitivity "
- (if case-sensitivity "on" "off"))))
-
- (@search (lambda ()
- (set-car! search-objects
- (ed 'with-status
- (lambda (mes)
- (ed 'display "Search for: " mes)
- (ed 'read-line mes))))
- (@repeat-search)))
-
- (@repeat-search (lambda ()
- (get-values)
- (let ((res (search clin (1+ ccol) (car search-objects))))
- (if res
- (ed 'position res)
- (ed 'notify "Target not found")))))
-
- (@translate (lambda ()
- (set-car! (cdr search-objects)
- (ed 'with-status
- (lambda (mes)
- (ed 'display "Translate what: " mes)
- (ed 'read-line mes))))
- (set-car! (cddr search-objects)
- (ed 'with-status
- (lambda (mes)
- (ed 'display "Replace with: " mes)
- (ed 'read-line mes))))
- (@repeat-translate)))
-
- (@repeat-translate (lambda ()
- (get-values)
- ((named-lambda (next line col global?)
- (let*
- ((res (search line col (cadr search-objects)))
- (curr (list-tail (ed 'buffer) (car res)))
- (todo
- (if global?
- (if res '(#t #t) '(#f))
- (if res
- (begin
- (ed 'position res)
- (ed 'with-status
- (lambda (mes)
- (ed 'display "Change ? (Yes No Global One Finished Abort)" mes)
- ((named-lambda (loop)
- (case (ed 'read-action)
- ((#\y #\Y) '(#t #f))
- ((#\n #\N) '(#f #f))
- ((#\g #\G) '(#t #t))
- ((#\o #\O) '(#t))
- ((#\f #\F) '(#f))
- ((#\a #\A) (set! clin (car res))
- (set! ccol (cadr res))
- '(#f))
- (else (loop))))))))
- (begin
- (ed 'notify "Target not found")
- '(#f))))))
- (when (car todo) ; Replace ?
- (set-car! curr
- (string-append
- (substring (car curr) 0 (cadr res))
- (caddr search-objects)
- (substring (car curr)
- (+ (cadr res)
- (string-length (cadr search-objects)))
- (string-length (car curr)))))
- (if (not global?) (ed 'refresh-line)))
- (if (cdr todo) ; Repeat ?
- (next (car res) (1+ (cadr res)) (cadr todo))
- (if global? (ed '@refresh)))))
- clin ccol #f)
- (ed 'position (list clin ccol))))
-
- ; Interface support
-
- (write-block (lambda (name)
- (when btyp
- (get-values)
- (do ((fil (open-output-file name))
- (curr (list-tail (ed 'buffer) top) (cdr curr))
- (n top (1+ n)))
- ((> n bot) (close-output-port fil))
- (let* ((str (car curr))
- (len (string-length str))
- (sran (srange n 0 len)))
- (display (ed 'tabulize (substring str (car sran) (cdr sran))) fil)
- (newline fil)))
- (gc #T))))
-
- (srange (lambda (line fcol lcol)
- (when btyp
- (get-values)
- (let ((blft (min lcol (max fcol bcol)))
- (brgt (min lcol (max fcol (1+ bcol))))
- (clft (min lcol (max fcol ccol)))
- (crgt (min lcol (max fcol (1+ ccol)))))
- (cond
- ((or (> line bot)
- (< line top)) #f)
- ((eq? btyp 'line) (cons fcol lcol))
- ((or (eq? btyp 'col)
- (and (= top bot) (= top line)))
- (cons (min blft clft) (max brgt crgt)))
- ((= line top) (cons (if (= top blin) blft clft) lcol))
- ((= line bot) (cons fcol (if (= top blin) crgt brgt)))
- (else (cons fcol lcol)))))
- ))
-
- (select (lambda l
- (begin0
- (list btyp blin bcol)
- (when l
- (when (not btyp)
- (set! mtyp (ed 'magic-move))
- (if mtyp (ed 'magic-move 'hard)))
- (set! btyp (caar l))
- (if btyp
- (begin (set! blin (cadar l))
- (set! bcol (caddar l)))
- (if mtyp (ed 'magic-move mtyp)))))))
-
- (search (lambda (clin ccol match)
- (let* ((find (if case-sensitivity
- substring-find-next-string
- substring-find-next-string-ci))
- (curr (list-tail (ed 'buffer) clin))
- (len (string-length (car curr))))
- (do ((line clin (1+ line))
- (pos (find (car curr) (min len ccol) len match)
- (find (car curr) 0 (string-length (car curr)) match)))
- ((or (null? (cdr curr)) pos) (if pos (list line pos)))
- (set! curr (cdr curr))))
- ))
-
- (click (lambda (left center right x y)
- (get-values)
- (cond
- ((> left 0) (ed 'position (list (+ flin (quotient y 8))
- (+ fcol (quotient x 8)))))
- ((> right 0) (select '(#f))))
- ))
-
- (mouse-block '(((LEFT) . CHAR)
- ((RIGHT) . LINE)
- ((CENTER) . COL)
- ((LEFT RIGHT) . COL)))
-
- (drag-start (lambda (buttons x y)
- (get-values)
- (select (list (cdr (assoc buttons mouse-block))
- (+ flin (quotient y 8))
- (+ fcol (quotient x 8))))))
-
- (drag (lambda (x y)
- (when (not (desktop 'pending?))
- (get-values)
- (let ((line (quotient y 8))
- (col (quotient x 8)))
- (ed 'position (list (+ flin line) (+ fcol col)))
- (ed 'refresh-lines (min (+ flin line) clin)
- (1+ (max (+ flin line) clin)))))))
-
- ; Message handling
-
- (jobs (append
- (list
- (cons '@mark-block (@mark 'char))
- (cons '@line-block (@mark 'line))
- (cons '@column-block (@mark 'col))
- (cons '@cancel-block @cancel-block)
- (cons '@copy-block @copy-block)
- (cons '@cut-block @cut-block)
- (cons '@delete-block @delete-block)
- (cons '@insert-block @insert-block)
- (cons '@write-block @write-block)
- (cons '@swap-anchor @swap-anchor)
- (cons '@replicate @replicate)
- (cons '@bookmark-1 (@bookmark 1))
- (cons '@bookmark-2 (@bookmark 2))
- (cons '@bookmark-3 (@bookmark 3))
- (cons '@jump-to-1 (@jump-to 1))
- (cons '@jump-to-2 (@jump-to 2))
- (cons '@jump-to-3 (@jump-to 3))
- (cons '@case-sensitivity @case-sensitivity)
- (cons '@search @search)
- (cons '@repeat-search @repeat-search)
- (cons '@translate @translate)
- (cons '@repeat-translate @repeat-translate)
- (cons 'scrap (lambda l (begin0 scrap (if l (set! scrap (car l))))))
- (cons 'bookmarks (lambda l (begin0 bookmarks (if l (set! bookmarks (car l))))))
- (cons 'case-sensitivity (lambda l (begin0 case-sensitivity (if l (set! case-sensitivity (car l))))))
- (cons 'search-objects (lambda l (begin0 search-objects (if l (set! search-objects (car l))))))
- (cons 'search search)
- (cons 'selection-range srange)
- (cons 'select select)
- (cons 'write-block write-block)
- (cons 'click click)
- (cons 'drag-start drag-start)
- (cons 'drag-move drag)
- (cons 'drag-end drag)
- )
- (ed 'jobs)))
-
- ) ; LETREC bindings
-
- (ed 'actions action-keys) ; initialization
- (ed 'specials special-keys)
- (ed 'jobs jobs)
- ed
-
- ) ; LETREC
- ) ; LAMBDA param
- ) ; SET! make-editor
- ) ; LET
-
-
- ;**************************************************************************
- ; Now customize the enhenced-editor do get a color editor...
-
-
- (define (make-color-editor . param)
- (letrec
- (
- (ed (apply make-enhanced-editor param))
- (win (ed 'window))
- (colors '((00 . #x07) (50 . #x0f) (100 . #x17) (150 . #x1f)
- (01 . #x0e) (51 . #x0f) (101 . #x1e) (151 . #x1f)
- (02 . #x0a) (52 . #x0f) (102 . #x1a) (152 . #x1f)
- (03 . #x0b) (53 . #x0f) (103 . #x1b) (153 . #x1f)
- (04 . #x0e) (54 . #x0f) (104 . #x1e) (154 . #x1f)
- (05 . #x0a) (55 . #x0f) (105 . #x1a) (155 . #x1f)
- (06 . #x0b) (56 . #x0f) (106 . #x1b) (156 . #x1f)
- (07 . #x0e) (57 . #x0f) (107 . #x1e) (157 . #x1f)
- (08 . #x0a) (58 . #x0f) (108 . #x1a) (158 . #x1f)
- (09 . #x0b) (59 . #x0f) (109 . #x1b) (159 . #x1f)
- (10 . #x0e) (60 . #x0f) (110 . #x1e) (160 . #x1f)
- (11 . #x0a) (61 . #x0f) (111 . #x1a) (161 . #x1f)
- (12 . #x0b) (62 . #x0f) (112 . #x1b) (162 . #x1f)
- (13 . #x0e) (63 . #x0f) (113 . #x1e) (163 . #x1f)
- (14 . #x0a) (64 . #x0f) (114 . #x1a) (164 . #x1f)
- (15 . #x0b) (65 . #x0f) (115 . #x1b) (165 . #x1f)
- (16 . #x0e) (66 . #x0f) (116 . #x1e) (166 . #x1f)
- (17 . #x0a) (67 . #x0f) (117 . #x1a) (167 . #x1f)
- (18 . #x0b) (58 . #x0f) (118 . #x1b) (158 . #x1f)
- (19 . #x0e) (69 . #x0f) (119 . #x1e) (169 . #x1f)
- (20 . #x0a) (70 . #x0f) (120 . #x1a) (170 . #x1f)
- (21 . #x0b) (71 . #x0f) (121 . #x1b) (171 . #x1f)
- (22 . #x0e) (72 . #x0f) (122 . #x1e) (172 . #x1f)
- (23 . #x0a) (73 . #x0f) (123 . #x1a) (173 . #x1f)
- (24 . #x0b) (74 . #x0f) (124 . #x1b) (174 . #x1f)
- (25 . #x0e) (75 . #x0f) (125 . #x1e) (175 . #x1f)
- (26 . #x0a) (76 . #x0f) (126 . #x1a) (176 . #x1f)
- (27 . #x0b) (77 . #x0f) (127 . #x1b) (177 . #x1f)
- (28 . #x0e) (78 . #x0f) (128 . #x1e) (178 . #x1f)
- (29 . #x0a) (79 . #x0f) (129 . #x1a) (179 . #x1f)
- (30 . #x0b) (80 . #x0f) (130 . #x1b) (180 . #x1f)
- (31 . #x0e) (81 . #x0f) (131 . #x1e) (181 . #x1f)
- (32 . #x0a) (82 . #x0f) (132 . #x1a) (182 . #x1f)
- ))
-
- ; Interface support
-
- (deepize (lambda (str clin)
- '((0 . (0 . 0)))))
-
- (memo '()) ; buffer for MRU detailed line deepness
- (upper-depth (list 0)) ; global deepness of first lines
- (upper-floor (list 0)) ; minimum deepness of first lines
-
- (ensure (lambda (clin) ; ensure upper- values are known until clin
- (let* ((plin (length upper-depth))
- (extend (named-lambda (extend curr depth flor plin)
- (if (= plin clin)
- (begin (set! upper-depth depth)
- (set! upper-floor flor))
- (let ((info (cdar (str-colors (car curr) plin))))
- (extend (cdr curr)
- (cons (+ (car depth) (car info)) depth)
- (cons (+ (car depth) (cdr info)) flor)
- (1+ plin))))))
- (doit (lambda ()
- (extend (list-tail (ed 'buffer) plin)
- upper-depth upper-floor plin))))
-
- (if (< plin clin)
- (if (> (- clin plin) 40)
- (ed 'with-status
- (lambda (mes)
- (ed 'display "Please wait..." mes)
- (doit)))
- (doit))))))
-
- (line-depth (lambda (clin)
- (ensure clin)
- (list-ref upper-depth (- (length upper-depth) clin))))
-
- (line-floor (lambda (clin)
- (ensure clin)
- (list-ref upper-floor (- (length upper-floor) clin))))
-
- (valid-line (lambda (clin deep) ; valid upper- knowledge with new data
- (let* ((base (line-depth clin))
- (next (line-depth (1+ clin)))
- (flor (line-floor (1+ clin)))
- (plin (length upper-depth)))
- (when (or (<> (- next base) (cadar deep))
- (<> (- flor base) (cddar deep)))
- (set! upper-depth (list-tail upper-depth (- plin clin)))
- (set! upper-floor (list-tail upper-floor (- plin clin))))
- base)))
-
- (str-colors (lambda (str clin) ; quickly find colors of str
- (let* ((deep (assq str memo))
- (buffer (ed 'buffer))
-
- (clean (named-lambda (clean memo prev scan size)
- (cond ((null? scan) memo)
- ((= size 0) (set-cdr! scan '()))
- (else (if (not (memq (car scan) buffer))
- (set-cdr! prev (cdr scan)))
- (clean memo (cdr prev) (cdr scan) (-1+ size)))))))
-
- (when (not deep)
- (set! deep (cons str (deepize str clin)))
- (set! memo (cons deep memo))
- (if (> (length memo) 100) (clean memo memo (cdr memo) 50)))
- (cdr deep))
- ))
-
- (write-line (lambda (win strg flin clin fcol lcol) ; fit-in and display a line
- (let* ((sran (ed 'selection-range clin fcol lcol))
- (diff (if sran (- (cdr sran) (string-length strg)) 0))
- (str (if (> diff 0)
- (string-append strg (make-string diff #\space))
- strg))
- (len (min (string-length str) lcol))
-
- (skip (named-lambda (skip deep)
- (if (or (null? (cdr deep)) (> (cdadr deep) fcol))
- deep
- (skip (cdr deep)))))
-
- (disp (named-lambda (disp from deep base len)
- (window-set-attribute! win 'text-attributes
- (cdr (or (assq (+ base (caar deep)) colors)
- (assq 0 colors))))
- (if (or (null? (cdr deep)) (> (cdadr deep) len))
- (begin (display (substring str from len) win)
- deep)
- (begin (display (substring str from (cdadr deep)) win)
- (disp (cdadr deep) (cdr deep) base len)))))
-
- (scol (str-colors str clin))
- (base (valid-line clin scol))
- (deep (skip scol)))
-
- (when (and win (or sran (> (string-length strg) fcol)))
- (window-set-cursor! win (- clin flin) 0)
- (if sran
- (disp (cdr sran)
- (disp (car sran)
- (disp fcol deep base (car sran))
- (+ base 100) (cdr sran))
- base len)
- (disp fcol deep base len))))
- ))
-
- (line-colors (lambda (clin)
- (str-colors (list-ref (ed 'buffer) clin) clin)))
-
- (with-cursor (lambda (proc) ; generic list search by cursor pos
- (lambda (clin ccol)
- (letrec ((str (list-ref (ed 'buffer) clin))
- (deep (str-colors str clin))
- (scan (lambda (curr ccol)
- (if (or (null? (cdr curr)) (> (cdadr curr) ccol))
- (proc deep curr str clin ccol)
- (scan (cdr curr) ccol)))))
- (scan deep ccol)))))
-
- (cursor-color (with-cursor
- (lambda (deep curr str clin ccol)
- (+ (list-ref upper-depth (- (length upper-depth) clin))
- (caar curr)))))
-
- (left-colors (with-cursor
- (lambda (deep curr str clin ccol)
- (let ((deep (copy deep)))
- (set-cdr! (car deep) 0)
- (list-tail (reverse! (if (> (caar deep) 0)
- (cons (cons 0 0) deep)
- deep))
- (-1+ (length curr)))))))
-
- (right-colors (with-cursor
- (lambda (deep curr str clin ccol)
- (reverse! (cons (cons (cadar deep) (string-length str))
- (reverse (cdr curr)))))))
-
- ; Message handling
-
- (jobs (append
- (list
- (cons 'colors (lambda l (begin0 colors (if l (set! colors (car l))))))
- (cons 'deepize (lambda l (begin0 deepize (if l (set! deepize (car l))))))
- (cons 'upper-depth (lambda l (begin0 upper-depth (if l (set! upper-depth (car l))))))
- (cons 'upper-floor (lambda l (begin0 upper-floor (if l (set! upper-floor (car l))))))
- (cons 'line-depth line-depth) ; get initial depth of a line
- (cons 'line-floor line-floor) ; get minimum depth of precedent line
- (cons 'valid-line valid-line) ; valid upper- data with new line
- (cons 'line-colors line-colors) ; get colors of a line
- (cons 'left-colors left-colors) ; idem, left of cursor, nearest first
- (cons 'right-colors right-colors); idem, right of cursor, nearest first
- (cons 'cursor-color cursor-color); get color of current position
- )
- (ed 'jobs)))
-
- ) ; LETREC bindings
-
- (ed 'jobs jobs) ; initialization
- (ed 'write-line write-line)
- (ed 'magic-move 'soft)
- ed)
- ) ; DEFINE
-
-
- ;**************************************************************************
- ; Let's see how to customize a color-editor to make a scheme-editor...
-
-
- (let* ; values shared by all editors
- ((indent-tokens '(define define-integrable macro case when apply set!
- lambda named-lambda rec let letrec let* fluid-let
- call-with-current-continuation call/cc
- with-input-from-file with-output-to-file
- call-with-input-file call-with-output-file
- autoload-from-file))
-
- (separators (string-append "()'`\","
- ((make-color-editor 'EXIT-FREELY)
- 'separators)))
-
- (tab-indent? (lambda (ed)
- (let* ((epos (ed 'position))
- (line (list-ref (ed 'buffer) (car epos))))
- (or (> (cadr epos) (string-length line))
- (= (cadr epos) 0)
- (substring-find-next-char-in-set
- separators 0 (string-length separators)
- (string-ref line (-1+ (cadr epos))))))))
-
- (action-keys
- (append
- (list
- (cons (list* 001) '@mark-expr) ; Ctrl-A
- (cons (list* 026) '@mark-def) ; Ctrl-Z
- (cons (list* 009) (list* (cons tab-indent? '@indent)
- '@completion)) ; Indent || completion
- (cons (list* 013) '@scheme-enter) ; Return && indent
- (cons (list* 041) '@scheme-parenthesis) ; Electric parenthesis
- (cons (list* 015 000) '@comment) ; Shift-tab
- (cons (list* 113 000) '@eval) ; Alt-F10
- (cons (list* 103 000) '@eval-block) ; Ctrl-F10
- )
- ((make-color-editor 'EXIT-FREELY) 'actions)))
- )
-
- (set! make-scheme-editor
- (lambda param
- (letrec
- (
- (ed (apply make-color-editor param))
-
- (ewin '())
- (epos '())
- (input-port '())
- (win #F)
- (nlin 0)
- (ncol 0)
- (clin 1)
- (ccol 0)
- (flin 1)
- (fcol 0)
- (draft-name "DRAFT$$$")
- (used draft-name)
- (comment-column 40)
-
-
- ; Help to inherit a fresh copy of current state variables
-
- (get-values (lambda ()
- (set! input-port (ed 'input-port))
- (set! ewin (ed 'window))
- (set! win (car ewin))
- (set! nlin (cadr ewin))
- (set! ncol (cddr ewin))
- (set! epos (ed 'position))
- (set! clin (car epos))
- (set! ccol (cadr epos))
- (set! flin (caddr epos))
- (set! fcol (cadddr epos))
- ))
-
- ; Key handling
-
- (mark (lambda (end delta)
- (let* ((epos (ed 'position))
- (right (expression 'end (car end) (cadr end) delta))
- (left (expression 'start (car epos) (cadr epos) delta)))
- (ed 'select (list 'char (car right) (max 0 (-1+ (cadr right)))))
- (ed 'position left)
- (ed 'refresh-lines (car left) (1+ (car right))))))
-
- (@mark-expr (lambda ()
- (let ((blk (ed 'select)))
- (if (car blk)
- (mark (cdr blk) 2)
- (mark (ed 'position) 1)))))
-
- (@mark-def (lambda ()
- (let ((epos (ed 'position)))
- (mark epos (ed 'cursor-depth (car epos) (cadr epos))))))
-
- (@completion (lambda ()
- (get-values)
- (ed 'modified #T)
- (let* ((curr (list-tail (ed 'buffer) clin))
- (str (car curr))
- (len (string-length str)))
- (when (>= len ccol)
- (let ((spc (substring-find-previous-char-in-set str 0 ccol separators)))
- (when (if (null? spc) #T (> ccol (1+ spc)))
- (let* ((mid ccol)
- (end (substring str ccol len))
- (sta (begin (ed '@word-left) (cadr (ed 'position))))
- (beg (substring str 0 sta)))
- ((named-lambda (loop)
- (let ((fnd (pcs-recognize-symbol (substring (car curr) sta ccol) (- mid sta))))
- (if (null? fnd) (set! fnd (substring str sta mid)))
- (set-car! curr (string-append beg fnd end))
- (set! ccol (+ sta (string-length fnd)))
- (set-car! (cdr epos) ccol)
- (ed 'position epos)
- (ed 'refresh-line)
- ((named-lambda (scan action)
- (if (pair? action)
- (if (eq? (cdar action) '@completion)
- (loop)
- (scan (cdr action)))
- (if (eq? action '@completion)
- (loop)
- (ed 'handle-action action))))
- (ed 'read-action))
- ))))))))
- (pcs-recognize-symbol 'done)
- ))
-
- (indentize (lambda (clin cind)
- (if (= clin 1)
- 0
- (let* ((buffer (ed 'buffer))
- (color (ed 'cursor-depth (-1+ clin) 32000))
- (cstr (list-ref buffer clin))
- (cchar (if (< cind (string-length cstr))
- (string-ref cstr cind)))
- (left (ed 'expression 'start (-1+ clin) 32000 1))
- (str (list-ref buffer (car left)))
- (len (string-length str))
- (sub (substring str (min (1+ (cadr left)) len) len))
- (p (open-input-string sub))
- (atom (read-atom p))
- (npos (get-file-position p))
- (next (read-atom p)))
- (cond ((memv color '(0 50)) 0)
- ((eqv? cchar #\)) (cadr left))
- ((or (eof-object? next)
- (memq atom indent-tokens)) (+ (cadr left) 2))
- ((equal? atom '(|(|)) (+ (cadr left) 1))
- (else (+ (cadr left) npos 2)))))))
-
- (indent-lines (lambda (start end)
- (do ((curr (list-tail (ed 'buffer) start) (cdr curr))
- (clin start (1+ clin))
- (pos 0))
- ((>= clin end) pos)
- (let ((cind (ed 'substring-skip (car curr) 0
- (string-length (car curr)))))
- (set! pos (indentize clin cind))
- (set-car! curr
- (string-append
- (ed 'make-blank pos)
- (substring (car curr) cind
- (string-length (car curr))))))
- (ed 'refresh-lines clin (1+ clin)))))
-
- (@indent (lambda ()
- (let* ((blk (ed 'select))
- (blin (cadr blk))
- (clin (car (ed 'position))))
- (if (car blk)
- (indent-lines (min blin clin) (1+ (max blin clin)))
- (ed 'position
- (list clin (indent-lines clin (1+ clin))))))))
-
- (@scheme-enter (lambda ()
- (ed '@enter)
- (ed '@indent)))
-
- (@scheme-parenthesis (lambda ()
- (get-values)
- (ed 'handle-action #\))
- (let* ((curr (list-tail (ed 'buffer) clin))
- (len (string-length (car curr)))
- (pos (expression 'start clin ccol 1))
- (str (list-ref (ed 'buffer) (car pos)))
- (width (ed 'with-status
- (lambda (mes)
- (min (-1+ (cdr (window-get-size mes)))
- (string-length str))))))
- (when (= ccol (ed 'substring-skip (car curr) 0 len))
- (indent-lines clin (1+ clin))
- (let ((diff (- len (string-length (car curr)))))
- (if (not (zero? diff))
- (ed 'position (list clin (- ccol diff -1))))))
- (ed 'notify (substring str (cadr pos) width)))))
-
- (@comment (lambda ()
- (get-values)
- (ed 'modified #T)
- (let* ((curr (list-tail (ed 'buffer) clin))
- (str (car curr))
- (len (string-length str)))
- (when (< len comment-column)
- (set! str (string-append str (ed 'make-blank (- comment-column len)))))
- (set-car! curr (string-append str "; "))
- (set-car! (cdr epos) (+ 2 (max len comment-column)))
- (ed 'position epos)
- (ed 'refresh-line))))
-
- (@eval (lambda ()
- (let ((l (reverse! (filename-split draft-name)))
- (ext (cadddr (filename-split (ed 'name)))))
- (if (ed 'modified)
- (begin
- (set! used (cons #T (filename-merge
- (reverse! (cons ext (cdr l))))))
- (ed 'save (cdr used)))
- (set! used (cons #F (ed 'name))))
- (ed 'todo 'eval)
- )))
-
- (@eval-block (lambda ()
- (let ((l (reverse! (filename-split draft-name)))
- (ext (cadddr (filename-split (ed 'name)))))
- (set! used (cons #T (filename-merge
- (reverse! (cons ext (cdr l))))))
- (ed 'write-block (cdr used))
- (ed 'todo 'eval)
- )))
-
- ; Interface support
-
- (deepize (lambda (str clin)
- (let* ((p (open-input-string str))
-
- (scan (named-lambda (scan p curpos curcol carry res low)
- (let* ((atom (read-atom p))
- (now (if (equal? atom '(|(|))
- (1+ (or carry 0))
- carry))
- (low (if carry (min low (+ carry curcol)) low))
- (nxt (if (equal? atom '(|)|)) -1)))
- (cond
- ((eof-object? atom)
- (let* ((endres (+ (or now 0) (if res (caar res) 0)))
- (endcol (cons 0 (cons endres low)))
- (comment
- (substring-find-next-char-in-set
- str curpos (string-length str) #\;)))
- (if comment
- (cons endcol (reverse!
- (cons (cons (+ endres 50)
- comment)
- res)))
- (cons endcol (reverse! res)))))
- (now (scan p (get-file-position p)
- (+ curcol now) nxt
- (cons (cons (+ curcol now) curpos) res) low))
- (else (scan p (get-file-position p) curcol nxt res low))))))
-
- (deep (scan p 0 0 #f '() 0)))
-
- (if (and (not (null? (cdr deep)))
- (= (cdadr deep) 0))
- (begin (set-cdr! (cadr deep) (cdar deep)) (cdr deep))
- deep))
- ))
-
- (cdepth (lambda (clin ccol left right base)
- (let ((line (list-ref (ed 'buffer) clin)))
- (if (< ccol (string-length line))
- (let* ((p (open-input-string (substring line (1+ ccol) (cdar right))))
- (corr (if (equal? (read-atom p) '(|(|)) -1 0)))
- (+ base (caar left) corr))
- (ed 'line-depth (1+ clin))))))
-
- (cursor-depth (lambda (clin ccol) ; more precise than cursor-color...
- (let* ((left (ed 'left-colors clin ccol)); bcoz between (A) (C) no color change
- (right (ed 'right-colors clin ccol))
- (base (ed 'line-depth clin)))
- (cdepth clin ccol left right base))))
-
-
- (expression (lambda (dir clin ccol delta)
- (let* ((fwd (eq? dir 'end))
- (left (ed 'left-colors clin ccol))
- (right (ed 'right-colors clin ccol))
- (base (ed 'line-depth clin))
- (color (cdepth clin ccol left right base))
- (buffer (ed 'buffer)))
- (letrec
- ((fpar (lambda (clin pos)
- (let ((str (list-ref buffer clin)))
- (list clin
- (substring-find-next-char-in-set
- str pos (string-length str) #\()))))
-
- (locate (lambda (color deep)
- (if (and (cdr deep)
- (or (and (= (1+ color) (caar deep))
- (= (1+ color) (caadr deep))
- (or (not fwd) (cddr deep)))
- (= color (caadr deep))))
- ((if fwd cdadr cdar) deep)
- (if (cddr deep) (locate color (cdr deep))))))
-
- (in-line (lambda (clin)
- (let* ((deep (if fwd
- (ed 'right-colors clin 0)
- (ed 'left-colors clin 32000)))
- (base (ed 'line-depth clin))
- (diff (- color delta base))
- (pos (cond
- ((and fwd (= diff 0)) 0)
- ((and fwd (= diff (caar deep))) (cdar deep))
- ((null? (cdr deep)) 0)
- (else (locate (- color base delta) deep)))))
- ((if fwd list fpar) clin pos))))
-
- (deep-scan (lambda (color flor dist)
- (if (>= color 0)
- (deep-scan (-1+ color) flor
- (max dist (length (memv color flor))))
- (in-line (-1+ dist)))))
-
- (wide-scan (lambda (color nlin)
- (if (<= (ed 'line-floor nlin) color)
- (in-line (-1+ nlin))
- (if (< nlin (length buffer))
- (wide-scan color (1+ nlin))))))
-
- (pos (locate (- color base delta)
- (if fwd (cons (car left) right) left))))
-
- (if fwd
- (cond ((>= color 50) (list clin (cdar right)))
- ((< color delta) (list (-1+ (length buffer))
- (string-length (car (last-pair buffer)))))
- (pos (list clin pos))
- (else (wide-scan (- color delta) (+ clin 2))))
- (cond ((>= color 50) (list clin (cdar left)))
- ((< color delta) (list 1 0))
- (pos (fpar clin pos))
- (else (let* ((flor (ed 'upper-floor))
- (len (length flor)))
- (deep-scan (- color delta)
- (list-tail flor (- len clin))
- 0)))))))
- ))
-
-
-
- ; Message handling
-
- (jobs (append
- (list
- (cons '@mark-expr @mark-expr)
- (cons '@mark-def @mark-def)
- (cons '@indent @indent)
- (cons '@completion @completion)
- (cons '@scheme-enter @scheme-enter)
- (cons '@scheme-parenthesis @scheme-parenthesis)
- (cons '@comment @comment)
- (cons '@eval @eval)
- (cons '@eval-block @eval-block)
- (cons 'cursor-depth cursor-depth) ; variant to cursor-color
- (cons 'expression expression) ; seek expression bounds
- (cons 'indent-lines indent-lines) ; indent a pack of lines
- (cons 'draft-name (lambda l (begin0 draft-name (if l (set! draft-name (car l))))))
- (cons 'comment-column (lambda l (begin0 comment-column (if l (set! comment-column (car l))))))
- (cons 'indent-tokens (lambda l (begin0 indent-tokens (if l (set! indent-tokens (car l))))))
- (cons 'indentize (lambda l (begin0 indentize (if l (set! indentize (car l))))))
- )
- (ed 'jobs)))
-
- (me (lambda args
- (let ((todo (apply ed args)))
- (case todo
- ('eval (load (cdr used))
- (if (car used) (dos-delete (cdr used)))
- *the-non-printing-object*)
- (else todo)))))
-
- ) ; LETREC bindings
-
- (ed 'separators separators) ; initialization
- (ed 'actions action-keys)
- (ed 'jobs jobs)
- (ed 'deepize deepize)
- (ed 'who me)
- me
-
- ) ; LETREC
- ) ; LAMBDA param
- ) ; SET! make-editor
- ) ; LET
-
-
- ;**************************************************************************
- ; Finally, this is the EXIT handler to avoid quitting without saving
-
- (let ((pcs-exit (access exit user-global-environment))
- (editors '()))
-
- (set! editor-handle-exit (lambda (it . ed)
- (cond
- ((eq? it 'remember) (set! editors (cons (car ed) editors)))
- ((eq? it 'forget) (set! editors (delq! (car ed) editors)))
- ((eq? it 'get-list) editors)
- (else (%error-invalid-operand 'editor-handle-exit it)))))
-
- (set!
- (access exit user-global-environment)
- (lambda args
- (if args
- (apply pcs-exit args)
- ((named-lambda (loop editors)
- (if (null? editors)
- (pcs-exit)
- (if ((car editors) 'safe)
- (loop (cdr editors))))) editors))
- (writeln "EXIT canceled on user request."))))